﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace BlunderBrain.VisualStudio.AviSynth
{
    public class AviSynthFunction
    {
        public string Name { get; private set; }
        public AviSynthFunctionParameter[] Parameters { get; private set; }

        public AviSynthFunction(string name, string parameterSpec)
        {
            this.Name = name;
            ParseParameterSpec(parameterSpec);
        }

        private void ParseParameterSpec(string spec)
        {
            Regex paramParser = new Regex(@"(\[(?<name>[^\]]*)\])?(?<type>[.cifsb]{1})(?<modifier>[\*\+]?)", RegexOptions.IgnoreCase);
            List<AviSynthFunctionParameter> parameters = new List<AviSynthFunctionParameter>();

            MatchCollection matches = paramParser.Matches(spec);
            this.Parameters = new AviSynthFunctionParameter[matches.Count];
            
            for(int i = 0; i < matches.Count; i++)
            {
                Match m = matches[i];
                AviSynthFunctionParameter param = null;
                switch (m.Groups["type"].Value.ToLower())
                {
                    case ".":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.Val);
                        break;
                    case "c":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.Clip);
                        break;
                    case "i":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.Int);
                        break;
                    case "f":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.Float);
                        break;
                    case "s":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.String);
                        break;
                    case "b":
                        param = new AviSynthFunctionParameter(AviSynthDataTypes.Bool);
                        break;
                    default:
                        param = new AviSynthFunctionParameter();
                        break;
                }

                if (m.Groups["name"].Success)
                {
                    param.Optional = true;
                    param.Name = m.Groups["name"].Value;
                }

                if (m.Groups["modifier"].Success)
                {
                    switch (m.Groups["modifier"].Value)
                    {
                        case "*":
                            param.Optional = true;
                            break;
                        case "+":
                            param.Repeating = true;
                            break;
                    }
                }

                this.Parameters[i] = param;
            }
            
        }
    }

    public class AviSynthFunctionParameter
    {
        public AviSynthFunctionParameter(AviSynthDataTypes type) : this()
        {
            DataType = type;
        }
        
        public AviSynthFunctionParameter()
        {
            Name = string.Empty;
            DataType = AviSynthDataTypes.Unknown;
            Optional = false;
            Repeating = false;
        }
        
        public string Name { get; set; }
        public AviSynthDataTypes DataType { get; set; }
        public bool Optional { get; set; }
        public bool Repeating { get; set; }
    }

    public enum AviSynthDataTypes
    {
        Unknown = 0,
        Val = 1,
        Clip,
        Int,
        Float,
        String,
        Bool
    }
}
